<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2018/5/14 0014
 * Time: 下午 3:35
 */

namespace App\Common;


use App\GameService\games\PlayNiuNiu;
use App\Model\User;
use App\Utility\DBTools;
use App\Utility\BaseEnum;
use App\Utility\RedisTools;
use App\Enum\SysEnum;
use EasySwoole\EasySwoole\Config;
use App\Enum\CardEnum;
use EasySwoole\EasySwoole\Task\TaskManager;

/**
 * TODO 互动玩法
 * TODO 公共的互动数据
 * @author XCH
 *
 */
class PlayCommon
{
    protected static $instance = null;
    public static $login_longtime = 7200;
    public static $notice_game_msg_max = 10;
    //用户状态
    const USER_STATUS = [0=>'禁用',1=>'正常',2=>'锁定',-1=>'删除'];
    
    /**
     * TODO 构造函数
     * @param array $options 参数
     * @access public
     */
    public function __construct($options = [])
    {
    }
    
    
    /**
     * TODO 统计随机概率数据
     * @param array $proArr
     * @return string| LIST 
     */
    public static function getRandKey($numsList = FALSE) {
        $result = FALSE ;
        $numkeys = !empty($numsList) ? array_keys($numsList) : FALSE;
        if(!$numsList || !$numkeys) return FALSE;
        $proSum = array_sum($numsList);     //概率数组的总概率精度
        $maxVal = max(array_keys($numsList));
        //TODO 概率数组循环
        foreach ($numsList as $key => $proCur) {
            $randNum = mt_rand(1, $proSum);
            if ($randNum <= $proCur) {
                $result = $key;
                if ($proCur == $maxVal && mt_rand(1,2) != 1) {  //最大值增加 1/2 
                    $result = reset($numkeys);
                }
                break;
            } else {
                $proSum = $proSum - $proCur;
            }
        }
        unset ($numsList);
        return $result;
    } 
    
    
    
    /**
     * TODO 机器人登录并加入列表中
     * @param number $robotId ID
     * @param boolean $freeUser 玩家信息
     * @return boolean
     */
    protected static function doLoginRobotInto($robotId,$freeUser = FALSE, $roomId = FALSE) {
        $loginFd = $robotId;
        $robotName = $freeUser['name'] ?? "";
        $agentId = $freeUser['recUid'] ?? 0;
        $roomId = ($roomId > 0) ? $roomId :0;
        if(!$robotId || empty($freeUser) || empty($robotName) || $agentId<=0) 
            return FALSE;
        
        $userInfo= [
            'uid' => $robotId,
            'name'=> $robotName,
            'group_id' => $freeUser['group_id'],
            'status' => $freeUser['status'],
            'recUid' => $agentId,
            'recUser'=> $freeUser['recUser'],
            'ancestor_ids'=>$freeUser['ancestor_ids'],
            'level' => $freeUser['level'],
            'realname' => $freeUser['realname'],
            'gender'=> $freeUser['gender'],
            'user_ident'=> $freeUser['user_ident'],
            'head_url' => $freeUser['head_url'],
            'points' => $freeUser['points'],
            'reg_ip' => $freeUser['reg_ip'],
            'fd' => $loginFd,
            'lastActiveTime' => time(),
            'onlineStatus' => 1,
            'onStatus' => 'ONLINE',
            'token' => BaseComm::createToken($robotId)
        ];
        //TODO 覆盖一个旧值会返回0
        RedisTools::Pool_set(SysEnum::USER_LOGIN_REDIS_KEY.$robotId,json_encode($userInfo),864000);                 //登录信息
        RedisTools::Pool_hSet(SysEnum::getLoginFdMapKey(),"login_".$loginFd , $robotId.'-'. $userInfo["token"]);  //登录TOKEN - FD 
        
        //TODO 机器人组的信息
        $robotDet = [
            'uid' => $robotId,
            'agentId' => $agentId,
            'name' => $robotName,
            'loginFd' => $loginFd,
            "toRoomId" => $roomId ?? 0,
            'gender' => $freeUser['gender'],
            'head_url' => $freeUser['head_url'],
            'points' => $freeUser['points'],
            'playFlag' => 2
        ];
        //TODO 缓存机器人列表和在线机器人列表
        $main_key = $robotId;
        $rbotkey = SysEnum::getRobotClientKey();
        if ($roomId > 0) {
            $main_key = $robotId."_" .$roomId;
            $rbotkey = SysEnum::getRobotClientKey()."_ROOMS" ; //不同房间的机器人玩家放在不同的位置保存
            BaseEnum::Logger("Robot登录：Uid={$robotId}，RobotName ={$robotName} joinWait SUCCESS --->>> " . json_encode(["fd"=> $loginFd]), 'user-login');
        }
        RedisTools::Pool_hSet($rbotkey,$main_key,json_encode($robotDet));                   //玩家信息
        RedisTools::Pool_hSet(SysEnum::ROBOT_ONLINEPLAYER_KEY,$robotId , 1);                //在线
        return TRUE;
    }
    
    
    /**
     * TODO 获取固定的机器人玩家列表；不够的话添加新的玩家
     */
    protected static function getReqRobotList($agentId , $roomId = FALSE,  $requireNum = 10 ,$agentName="",$agentAids = "" ){
        $userTable = 'qc_user';
        $siteId = BaseComm::getSiteId();
        $robotNameFirst = "robot{$siteId}_";
        $pfield = ["uid","name","recUid","recUser","group_id","status","level","realname","ancestor_ids","points","head_url","gender","isNation","user_ident","reg_ip"];
        if (!$agentAids) { $agentAids = '10000'; }
        $roomId = isset($roomId) ? intval($roomId) : 0 ;
        $lineCode = "{$siteId}_{$roomId}";
        //TODO 查询出1000个代理玩家出来
        $whereOps = array('recUid'=> ['text' => $agentId,"mark"=> '='],'isNation'=> ['text' => 3,"mark"=> '='],"lineCode"=> ['text' => $siteId ,"mark"=> '=']);
        if ($roomId > 0 ) {
            $robotNameFirst = "robot{$roomId}_";
            $whereOps["lineCode"] = ['text' => $lineCode,"mark"=> '='];
        }
        
        $allPlayers = DBTools::PoolGet($userTable,$requireNum,$pfield,$whereOps);
        $robotRnum = !empty($allPlayers) ? sizeof($allPlayers) :0 ;
        
        //TODO 是否添加机器人（不够人就添加新的机器玩家）
        $allNames = !empty($allPlayers) ? array_column($allPlayers, "name","uid") : FALSE;
        $maxRobot = !empty($allNames) ? max($allNames) : "";
        BaseEnum::Logger("扫描到[RoomId={$roomId}]机器人玩家(真实个数：{$robotRnum}个 -- {$robotNameFirst} ) ; 其中最后一个玩家Name=>{$maxRobot};","user-login");
        
        //TODO 人数是否达到标准值；
        $newUids = [];
        if($robotRnum < $requireNum){
            //添加新的机器人玩家信息
            $start_inii = !empty($maxRobot) ?  intval(str_replace($robotNameFirst, "", $maxRobot))  : 0 ;
            $ancestor_ids = $agentAids.','.$agentId;
            $every_index = 0;
            for ($i = $robotRnum; $i < $requireNum; $i++) {
                $every_index ++;
                $newIndex = $start_inii + $every_index;
                $newName = ($newIndex <= 1000) ? $robotNameFirst . str_pad($newIndex,4,'0',STR_PAD_LEFT) :  $robotNameFirst .$newIndex ;
                //创建一个玩家
                $oneUser = array(
                    'name' => $newName,
                    'realname' => $newName,
                    'password' => '',
                    'group_id' => 1,
                    'status' => 1,
                    'recUid' => $agentId,
                    'recUser' => $agentName,
                    'ancestor_ids' => $ancestor_ids,
                    'level' => 1,
                    'points' => mt_rand(2000,50000),
                    'isNation' => 3,
                    'reg_time' => time(),
                    'reg_ip' => '127.0.0.1',
                    'gender' => array_rand([0,1,2],1),
                    'head_url' => AuthCommon::randerUserHeadId(), //array_rand([0,1,2,3,4,5,6,7])
                    'user_ident' => 1,
                    "lineCode"=> ($roomId>0) ? $lineCode :$siteId 
                );
                $robotLastId = DBTools::PoolInsert($userTable,$oneUser,TRUE);   //加入新的机器人玩家
                if (isset($robotLastId) && intval($robotLastId) >0) {
                    @array_push($newUids, $robotLastId);
                    unset($oneUser);
                }
            }
            BaseEnum::Logger("创建新的机器人成功 ：UID= " . json_encode($newUids),"user-login");
            //返查所有数据
            if (!empty($newUids)) {
                $allPlayers = DBTools::PoolGet($userTable,$requireNum,$pfield,$whereOps);
                BaseEnum::Logger("重新查询一次玩家列表 ： 获取所完整的机器人列表数据 ====> Finish .","user-login");
            }
        }
        return $allPlayers ?? FALSE;
    }
    
    
    //TODO 服务启动时添加机器人部署功能
    public static function initRobotLoginGame($agentId = 0,$startNum = 1000){
        $userModel = new User();
        try {
            $agentInfo = $agentId ? $userModel->getAgentById($agentId,["uid","name","ancestor_ids"]) :FALSE;
            $agentName = $agentInfo["name"] ?? "";
            $agentAids = $agentInfo["ancestor_ids"] ?? "10000";
            BaseEnum::Logger("查询机器人代理： (Name={$agentName}) =>" . json_encode($agentInfo),"user-login");
            if(!$agentId || empty($agentInfo) || empty($agentName)){
                return FALSE;
            }
            
            //TODO 查询出1000个代理玩家出来
            $allPlayers = self::getReqRobotList($agentId,FALSE,$startNum,$agentName,$agentAids);
            
            //TODO 是否达标； 则执行登录和分组缓存机器人
            if(empty($allPlayers)){
                BaseEnum::Logger("扫描到(RoomId={$agentId})机器人玩家：暂无机器人玩家 !!!!!" ,"user-login");
            }
            
            $totalNum = 0;
            $robotList = [];
            //TODO 执行登录和分组；
            foreach ($allPlayers as $oneUsr){
                $robotId = $oneUsr['uid'] ?? 0;
                $robotName = $oneUsr['name'] ?? "";
                if ($robotId>0 && !empty($robotName)) {
                    $stat = self::doLoginRobotInto($robotId,$oneUsr,FALSE);         //通用的ROBOT
                    $totalNum = ($stat == TRUE) ? $totalNum + 1 : $totalNum;
                    if($totalNum < 5){
                        $robotList[] = ["robot"=> $robotId.'-' . $robotName ,"status"=> $stat];
                    }
                }
            }
            BaseEnum::Logger("机器人操作完成(成功登录共{$totalNum}位)  处理结果=>".json_encode($robotList) ,"user-login");
            
            //TODO ====================房间内的机器人玩家===============================//
            $roomIdRes = [1050=> 10 ,1051=>10,1052=> 10 ,1053=>10];
            if (!$roomIdRes) {
                return FALSE;
            }
            $total2 = 0;
            $roomRobList = [];
            //TODO 每个房间开启机器人
            foreach ($roomIdRes as $roomId => $room_robot_num){
                
                //TODO 查询出1000个代理玩家出来
                $roomRobots = self::getReqRobotList($agentId,$roomId,$room_robot_num,$agentName,$agentAids);
                $roomRNames = !empty($roomRobots) ? array_column($roomRobots, "name","uid") : FALSE;
                
                //TODO 是否达标； 则执行登录和分组缓存机器人
                if(!empty($roomRobots)){
                    BaseEnum::Logger("扫描到(RoomId={$agentId}_1050)机器人玩家：".json_encode($roomRNames) ,"user-login");
                    foreach ($roomRobots as $onePob){
                        $robotiid = $onePob['uid'] ?? 0;
                        $robotNa2 = $onePob['name'] ?? "";
                        if ($robotiid>0 && !empty($robotNa2)) {
                            $stat2 = self::doLoginRobotInto($robotiid,$onePob, $roomId);     //TODO 执行登录和分组；
                            $total2 = ($stat2 == TRUE) ? $total2 + 1 : $total2;
                            $roomRobList[$roomId] = ["robot"=> $robotiid.'-' . $robotNa2 ,"status"=> $stat2];
                        }
                    }
                }else{
                    BaseEnum::Logger("扫描到(RoomId={$agentId}_1050)机器人玩家：暂无机器人玩家 !!!!!" ,"user-login");
                }
            }
            BaseEnum::Logger("[ROOM]机器人执行完成 (登录共{$total2}位)  =>".json_encode($roomRobList) ,"user-login");
        } catch (\Throwable $throwable) {
            BaseEnum::Logger("机器人启动失败=>" . $throwable->getMessage(),"user-login");
        }
    }

    
    //TODO 清掉所有机器人玩家
    public static function clearAllRobotPlayer(){
        $allrobkey = SysEnum::getRobotClientKey();
        $userFdkey  = SysEnum::getLoginFdMapKey();
        $userinfokey  = SysEnum::USER_LOGIN_REDIS_KEY;
        $delKeys = [$allrobkey,$allrobkey."_ROOMS"];
        
        //TODO 处理KEY的删除
        foreach ($delKeys as $one_firkey){
            $robots = RedisTools::Pool_hGetAll($one_firkey) ; //所有机器人
            $robotNum = !empty($robots) ? sizeof($robots) :0 ;
            BaseEnum::Logger("所有Robots：[{$one_firkey}] =>  共有机器人玩家数目： NUM = "  . $robotNum  ,"user-login");
            if (!empty($robots)) {
                //所有行数据
                foreach ($robots as $onevalue){
                    $oneObj = !empty($onevalue) ? json_decode($onevalue,TRUE): FALSE;
                    $loginuid = $oneObj['uid'] ?? 0;
                    $loginfid = $oneObj['fd'] ?? 0;                             //查询FD
                    if($loginuid && intval($loginuid) >0){
                        RedisTools::Pool_del($userinfokey.$loginuid);           //删除玩家信息
                    }
                    if($loginfid && intval($loginfid) >0){
                        RedisTools::Pool_hDel($userFdkey, "login_". $loginfid); //删除FD对应的UID字段
                    }
                }
                RedisTools::Pool_del($one_firkey);              //执行删除
            }
            return TRUE;
        }
    }
    
    
    /**
     * TODO 判断游戏GameId下边的玩家是否有掉线FD
     * @param number $gameId
     * @param boolean $userList
     * @return boolean 是否要结束游戏
     */
    public static function gameUserIsFinish($gameId,$userList = FALSE) {
        $lastStatus = FALSE;
        $userredKey = SysEnum::USER_LOGIN_REDIS_KEY;
        if (!empty($userList)) {            
            $downNum = 0;
            //TODO 验证玩家是否正常在线
            foreach ($userList as $oneplayer){
                $tempFd = $oneplayer['fd'] ?? 0;
                $curUid = $oneplayer['uid'] ?? 0;
                $isNats = $oneplayer['isNation'] ?? 0;
                if (intval($isNats) == 3 || $tempFd <= 0 || $curUid <= 0) continue;
                //FD检测状态是否正常；
                $udetail = RedisTools::Pool_get($userredKey.$curUid);
                $uDet = !empty($udetail) ? json_decode($udetail,TRUE): FALSE;
                
                //USER 不正常处理
                if (isset($uDet['onStatus']) && !empty($uDet['onStatus']) && strtoupper($uDet['onStatus']) == 'DOWN') {
                    $downNum ++ ;
                }
            }
            //结束后
            $lastStatus =  ($downNum > 0)  ? TRUE : FALSE;
        }
        return $lastStatus;
    }
    
    //TODO 匹配分配机器人(寻找固定的空闲机器人)
    public static function getFreeRobotsUser($gameId,$maxPeop = 1) {
        $succRobots = [];
        $allrobkey = SysEnum::getRobotClientKey();
        $allRobotUids = RedisTools::Pool_hAllKeys($allrobkey) ;   //所有机器的UID值； 
        if(!$allRobotUids)return FALSE;
        //获取空闲机器人的数据
        foreach ($allRobotUids as $oneUid) {
            //获取当前机器人是否为空闲状态
            $udetail = RedisTools::Pool_hGet($allrobkey, $oneUid);
            $robotInfo = !empty($udetail) ? json_decode($udetail,TRUE) :FALSE ; 
            $robuid = $robotInfo['uid'] ?? 0;
            if (!empty($robotInfo) && isset($robotInfo['playFlag']) && $robuid == $oneUid  && intval($robotInfo['playFlag']) == 2) {  //空闲状态
                $succRobots[$robuid] = $robotInfo;
                //TODO 个数判断
                if(!empty($succRobots) && sizeof($succRobots) >= $maxPeop) break;
            }
        }
        if (!empty($succRobots)) {
            foreach ($succRobots as $oneuid => $onerobot){
                $onerobot['playFlag'] = 1;  //修改为正在游戏中
                RedisTools::Pool_hSet($allrobkey, $oneuid , json_encode($onerobot));    //更新机器人列表数据
            }
        }
        return $succRobots ?? FALSE;
    }

    //TODO 房间内固定的机器人(取当前房间内的机器人)
    public static function getRoomRobotsUser($gameId,$roomId = 0,$maxPeop = 50) {
        $succRobots = [];
        $allrobkey = SysEnum::getRobotClientKey().'_ROOMS';
        $allRobotUids = RedisTools::Pool_hAllKeys($allrobkey) ;   //所有机器的UID值；
        if(!$allRobotUids || !$roomId)return FALSE;
        //TODO 获取空闲机器人的数据
        foreach ($allRobotUids as $oneRoomUid) {
            //只取当前机器人信息为当前房间内的玩家
            $udetail = RedisTools::Pool_hGet($allrobkey, $oneRoomUid);
            $robotInfo = !empty($udetail) ? json_decode($udetail,TRUE) :FALSE ;
            $robuid = $robotInfo['uid'] ?? 0;
            $robroomid = $robotInfo['toRoomId'] ?? 0;
            if (!empty($robotInfo) && intval($robroomid) > 0  && intval($robuid) > 0) {         //TODO 只拿当前房间内的Robot
                $robotInfo['playFlag'] = 1;                                                     //TODO 修改为正在游戏中
                $succRobots[$robuid] = $robotInfo; 
                RedisTools::Pool_hSet($allrobkey, $oneRoomUid , json_encode($robotInfo));       //TODO 更新机器人列表数据
                if(!empty($succRobots) && sizeof($succRobots) >= $maxPeop) break;               //TODO 个数判断
            }
        }
        return $succRobots ?? FALSE;
    }

    //TODO 组装推送数据格式
    public static function getPushContextByType($pushType,$pushContent = FALSE,$fdList = []) {
        $pushRes = FALSE;
        $pushdata = !empty($pushContent) ?  unserialize($pushContent) : FALSE;
        if($pushType === FALSE) $pushRes = $pushContent;
        
        if (!empty($pushType) && !empty($pushdata) && is_array($pushdata)) {
            $pushType = strtoupper($pushType);
            switch ($pushType){
                case 'USER_MONEY': 
                    $pushRes['m'] = BaseEnum::XYM_0X05;
                    $pushRes['data'] = array_merge($pushdata,["time"=> BaseEnum::getNowTime(TRUE)]);
                    break;
                case 'USER_OFFLINE':
                    TaskManager::getInstance()->async(function() use($fdList){
                        foreach ($fdList as $fd) {
                            AuthCommon::kickLoginFd($fd);
                        }
                    });
                    $pushRes = ['m'=>BaseEnum::XYM_0X02,"data"=>$pushdata,"code"=>BaseEnum::MSG_0XE5, "level"=> SysEnum::RETURN_MSG_LEVEL_3,"msg"=> "玩家强制下线，游戏结束。"];
                    break;
                case SysEnum::PUSH_MSGTYPE_USER_DOWNLING :
                    //被挤下线
                    $pushRes = ['m'=>BaseEnum::XYM_0X02,"data"=>$pushdata,"code"=>BaseEnum::MSG_0XF7, "level"=> SysEnum::RETURN_MSG_LEVEL_3,"msg"=> "系统下线通知，您的账号在其它地方登录。"];
                    break;
                default:  
                    $pushRes = FALSE; 
                    break;
            }
        }
        return !empty($pushRes) ? json_encode($pushRes) : FALSE;
    }
    
    //TODO 游戏结束后机器人空闲标识
    public static function doBackFreeRobot($gameId,$robotIds = FALSE){
        $succNum = 0;
        $allrobkey = SysEnum::getRobotClientKey();
        if(!$robotIds)return FALSE;
        //获取空闲机器人的数据
        foreach ($robotIds as $oneUid) {
            //获取当前机器人是否为空闲状态
            $udetail = RedisTools::Pool_hGet($allrobkey, $oneUid);
            $robotInfo = !empty($udetail) ? json_decode($udetail,TRUE) :FALSE ;
            $robuid = $robotInfo['uid'] ?? 0;
            if (!empty($robotInfo) && isset($robotInfo['playFlag']) && $robuid == $oneUid  && intval($robotInfo['playFlag']) == 1) {  //重置为空闲状态
                $succNum ++ ;
                $robotInfo['playFlag'] = 2;
                RedisTools::Pool_hSet($allrobkey, $oneUid , json_encode($robotInfo));    //更新机器人列表数据
            }
        }
        return $succNum ? TRUE : FALSE;
    }
    
    
    /**
     * TODO 自动分配机器人用户(分配智能机器人)；
     * @param int $gameId 游戏ID
     * @param int $roomId 房间ID
     * @param number $maxPeop 分配人员数
     */
    public static function gameSelfPlay($gameId,$roomId,$maxPeop = 1) {
        //分配玩家ID；
        //机器人的信息不参与登录，只参与游戏和结算过程； 暂时不考虑钱的问题。
        //玩家Play加入机器人列表；
    }
    
    
    //TODO 一局中机器人信息
    public static function getGameRobotsUser($gameId, $gameNo = FALSE,& $allClientFds = FALSE ,&$realUserId = FALSE){
        $allRobotUsers=[];
        //TODO 机器人列表下注操作(下注最低倍数)
        $fjDetail = BaseComm::distMemoryRooms($gameNo,FALSE);
        $allUsers = $fjDetail['lists'] ?? FALSE;
        if(!empty($allUsers)){
            $allClientFds = !empty($allUsers) ? array_column($allUsers, "fd","seatNo") : FALSE;
            foreach ($allUsers as $oneuid => $oneuuo){
                $oneuid = $oneuuo['uid'] ?? 0;
                if(isset($oneuuo['isNation']) && intval($oneuuo['isNation']) === 3 ){
                    $allRobotUsers[$oneuid] = $oneuuo;     //保留机器人玩家
                }else{
                    $realUserId[$oneuid] = $oneuuo['seatNo'] ?? -1;
                }
            }
        }
        return !empty($allRobotUsers) ? $allRobotUsers : FALSE;
    }
    
    
    /**
     * TODO 百人牛牛类型的游戏自动分配机器人
     * @param int $gameId
     * @param boolean $roomInfo
     * @param number $robNum
     * @return array 游戏玩家数据
     */
    public static function getHundRobotUsers($gameId,$roomInfo = FALSE,$robNum = 1){
        $groupPlayers = [];
        $roomId = $roomInfo["roomId"] ?? 0;
        $maxRoomPeop = Config::getInstance()->getConf('COMMON.BR_ROOM_PEOPNUMBER');                 //本项目配置百人类人数
        if(!$maxRoomPeop) $maxRoomPeop = 10;
        /**
         * $freePlayer = [
            10016=> ["uid"=> 10016,"name"=> "robot0001","agentId"=> 10010,"gender"=> 0,"head_url"=> 2,"loginFd"=> 300,"isNation"=>3],
            10017=> ["uid"=> 10017,"name"=> "robot0002","agentId"=> 10010,"gender"=> 0,"head_url"=> 2,"loginFd"=> 301,"isNation"=>3],
            10018=> ["uid"=> 10018,"name"=> "robot0003","agentId"=> 10010,"gender"=> 0,"head_url"=> 2,"loginFd"=> 302,"isNation"=>3]
        ];
         */
        $freePlayer = self::getRoomRobotsUser($gameId,$roomId,$maxRoomPeop);
        if(!$freePlayer){ return FALSE; }
        foreach ($freePlayer as $userid => $oneplayer){
            if($userid > 0 && !empty($oneplayer) && isset($oneplayer['loginFd']) && intval($oneplayer['loginFd']) >0){
                $playName = $oneplayer['name'] ?? FALSE;
                $groupPlayers[] = [
                    "uid" => $userid,
                    'name' => BaseComm::hiddenUserName($playName),                          // 名字
                    'fullName' => $playName,                                                // 名字
                    "isNation" => 3 ,   // 玩家身份信息
                    "agentId" => isset($oneplayer['agentId']) ? intval($oneplayer['agentId']) : 0,        // 代理用户ID
                    "sex" => isset($oneplayer['gender']) ? intval($oneplayer['gender']) : 0,            // 性别
                    "head_id" => isset($oneplayer['head_url']) ? intval($oneplayer['head_url']) : 0,    // 头像
                    "fd" => isset($oneplayer['loginFd']) ? intval($oneplayer['loginFd']) : 0,           // 客户端FD,
                    "points" => AuthCommon::getLoginUserPoints($userid),
                    "pstatus" => 0,         // 默认为0
                    "notBetConut" => 0,     //下注次数
                ];
            }
        }
        return $groupPlayers;
    }
    
    /**
     * TODO 给机器人UID添加游戏分
     * @param int $currUid
     * @param float $smallMoney
     * @param number $newpoints
     */
    public static function addRobotPoints($currUid,$smallMoney,&$newpoints = 0){
        $userTable = "qc_user";
        if($currUid){
            $DBObj = DBTools::getPoolDB();          //DB连接对象；
            try {
                $DBObj->startTransaction();          //开启事务
                $oneuser = $DBObj -> where('uid',$currUid) -> where('isNation',3) ->selectForUpdate(TRUE) -> getOne($userTable , ["uid",'points']);
                BaseEnum::Logger('机器人信息：uid:' .$currUid. '  user: '.json_encode($oneuser), 'user-login');
                $oldVal = $oneuser['points'] ?? 0 ;
                if (!empty($oneuser) && isset($oneuser['uid']) && intval($oneuser['uid']) == $currUid) {
                    $newpoints = rand(5,10) * $smallMoney  + $oldVal; //修改为新余额操作
                    $user_rows = $DBObj ->where("uid",$currUid)-> update($userTable, ["points" => $newpoints]);
                    if(!$user_rows){
                        throw new \Exception("暂未更新",-1);
                    }
                }
                $DBObj ->commit() ;         //确认提交事务；
                return TRUE;
            } catch (\Exception $e) {
                $DBObj -> rollback();
                BaseEnum::Logger('机器人加分失败：(addRobotPoints) uid={$currUid}code:' .$e->getCode() . '  msg: '. $e->getMessage(), 'user-login');
            }finally {
                DBTools::destPoolDB($DBObj);    //释放Pool
            }
        }
        return FALSE;
    }
    
    //游戏复原；
    public static function gameReCover($param) {
        
        //只要游戏没有结束就换掉用户的客户端FD值，否则推送出错；
        /* if(!empty($gamePlays)){
            foreach ($gamePlays as $r => $oneline){
                if(isset($oneline['uid']) && intval($oneline['uid']) === $userid){
                    $gamePlays[$r]['fd'] = $loginUserFd ;       // 当前登录用户的客户FD值；
                }
            }
            $gamedata['lists'] = $gamePlays;                    //修改后的数据重新给值
            BaseComm::distMemoryRooms($gameNo,TRUE,$gamedata);  //保存数据
            BaseEnum::wirteRedisData(SysEnum::ONLINE_ROOMS_LIST_KEY . $gameNo, json_encode($gamedata)); // 缓存；
        }
        BaseEnum::Logger("掉线重连：AuthCommon --> checkGamesOnline-[{$userid},$gameNo]-------gameData-->".json_encode($gamedata),'user-login');
        //查询当前游戏状态：
        if (!empty($gamedata) && $gameStatus >= 0  && in_array($gameStatus, [0,1,2,3,4,5]) && !empty($gamePlays)) {              //大于1 都是游戏中；
            $steps = BaseEnum::GAME_STEP;
            $stepName = isset($steps[$gameStatus]) ? $steps[$gameStatus] : "-";
            //显示游戏中的数据结构：定义新的结构；
            $returnData = array("gameId"=>$gameId,"roomId"=> $roomId,"gameNo"=> $gameNo ,"step"=> $stepName,"status"=> $gameStatus ,"lists" => []);
            //恢复游戏数据： 只处理以下几张情况；
            //1、抢庄中---谁庄过庄（标识出来），
            //2、下注中(谁是庄家标识出来，)
            //3、结算中(庄家，下注倍数，当前玩家牌值内容)
            $gameResult = self::ReBackGameData($gameId,$gameNo,$gameStatus,$gamePlays,$userid);
            if (!$gameResult) { return FALSE; }
            //显示每个玩家的数据内容；
            $returnData["lists"]= $gameResult;
            return TRUE;
        } */
    }
    
    
    /**
     * TODO 恢复游戏数据；
     * TODO 根据不同的游戏类型来处理
     */
    protected static function ReBackGameData($gameId,$gameNo,$gameStatus,$gamePlays = FALSE,$loginUid = FALSE){
        $result = FALSE ;//抢庄牛牛： 恢复数据结构
        if(!$gamePlays) return FALSE ;
        if ($gameId == 101) {
            $result = PlayNiuNiu::reBackData($loginUid,$gameStatus,$gameNo,$gamePlays);
        }else{
            
        }
        return $result;
    }

    
    /**
     * TODO 处理游戏结束发送起推送标准存入缓存
     * @param number $gameId
     */
    public static function gameNoticeSaveCache($gameId,$gameNo,$realInfo = FALSE) {
        $notice_key = SysEnum::USERWIN_NOTICE_KEY . $gameId;
        BaseEnum::Logger("加入通知：logger-GameId={$notice_key} , {$gameNo} ,游戏数据： ".json_encode($realInfo) ,"user-login");
        
        //TODO 每局游戏存入一个值；
        $nowStamp = BaseEnum::getNowTime(FALSE);
        $oneDom = (!empty($realInfo) && is_array($realInfo)) ? reset($realInfo) : FALSE ;
        $roomId = $oneDom['roomId'] ?? 0 ;
        if (!empty($realInfo) && !empty($oneDom) && $roomId > 0) {
            $roomInfo = BaseComm::GameRoomDetail($roomId);
            //取房间内的房间；
            $roomName = $roomInfo['gfFullName'] ?? "未知房间";
            $maxUser = FALSE;
            $oldMon = 0;
            foreach ($realInfo as $oneinfo){
                $pmoney = $oneinfo["changeMoney"] ?? 0;
                if (!$maxUser || (floatval($oldMon)>0 && floatval($pmoney) > 0 && $pmoney >$oldMon)) {
                    $maxUser = $oneinfo;
                    $oldMon = $maxUser["changeMoney"] ?? 0;
                }
            }
            //获取消息模板； {"14538":{"userName":"10015_abc001","roomId":1010,"changeMoney":3.8}}
            $messageContent = self::createMsgModel($maxUser,$roomName);
            if (!empty($messageContent)) {
                $msgObj = ["content"=> $messageContent,"timestamp"=> $nowStamp,"push_stauts"=> 0];
                RedisTools::Pool_hSet($notice_key, $nowStamp, json_encode($msgObj));        //TODO 存入游戏中的数据把玩家赢的消息存入列表中
            }
        }
        
        //TODO 检测是否超过30条，否则删除；
        $allNoticeKeys = RedisTools::Pool_hAllKeys($notice_key);
        $all_tongji = !empty($allNoticeKeys) ? sizeof($allNoticeKeys) :0;
        if (!empty($allNoticeKeys) && $all_tongji > self::$notice_game_msg_max) {
            @rsort($allNoticeKeys);     //降序排列
            for ($i = self::$notice_game_msg_max; $i < $all_tongji; $i++) {
                $main_key = $allNoticeKeys[$i] ?? -1;
                if(isset($main_key) && intval($main_key)>0) {
                    RedisTools::Pool_hDel($notice_key, $main_key);
                }
            }
        }
        //TODO 检测处理完
        return TRUE;
    }
    
    
    
    /**
     * TODO 对游戏玩家的牌进行杀号处理
     * @param number $gameId
     * @param array $CellUserIds
     * @param boolean $cardList
     */
    public static function gameKillPlayers($gameId,$CellUserIds, & $cardList = FALSE){
        if (empty($CellUserIds) || empty($cardList)) {
            return FALSE;
        }
        $userCards = [];
        $tempuserSids = [];
        $robotCards = $cardList;
        BaseEnum::Logger("杀号开始->{$gameId} , -> 真实玩家ID-->>>" . json_encode($CellUserIds)." 牌局数据：".json_encode($cardList) , 'user-login');
        
        
        //TODO 代理线盈利额(要开始赚线====>杀玩家号)
        foreach ($CellUserIds as $oneUid => $oneSid ){
            $vcards = $robotCards[$oneSid] ?? FALSE;
            if(!empty($vcards)){    //TODO 处理UID值
                $userCards[$oneUid] = ['seatNo'=>$oneSid,"cards"=> $robotCards[$oneSid] ?? FALSE];
                $tempuserSids[]=$oneSid;
            }
        }
        BaseEnum::Logger("第一步：拆牌.  真实玩家Cards-->>>" . BaseEnum::JsonEncode($userCards)."  和机器人Cards：".BaseEnum::JsonEncode($robotCards) , 'user-login');
        
        //TODO 处理 玩家游戏号码 ====抢庄牛牛
        if(!empty($userCards) && sizeof($userCards) > 0){
            
            BaseEnum::Logger("第二步：比牌开始->>>" . json_encode($userCards) , 'user-login');
            foreach ($userCards as $pUid => $pseta) {
                $pcards=$pseta["cards"] ?? -1;
                $pseatId=$pseta["seatNo"] ?? -1;
                
                //TODO 处理 所有玩家所在代理线的盈亏状态
                $killReq = SumComm::getOneAgentWins($pUid);
                $kpdotts = $killReq["kill_dotteds"] ?? 0;
                $kill_hand = (isset($killReq["killed"]) && $killReq["killed"] === TRUE) ? TRUE : FALSE;
                if ($kill_hand !== TRUE) {
                    //TODO 不杀号，但是根据概率计算
                    if($kpdotts != 100 && $kpdotts > 0 ){
                        $kill_hand = (rand( 0 ,$kpdotts) == 1) ? TRUE : FALSE;
                    }
                }
                BaseEnum::Logger("TO是否要Kill_ED=====>检查玩家代理线状况  (UID={$pUid}，概率:{$kpdotts}% )-是否Killed：{ $kill_hand } ==> 盈亏状况：" . json_encode($killReq), 'user-login');
                
                //TODO 场景处理
                if (!empty($pcards) && intval($pseatId)>= 0  && $kill_hand === TRUE) {
                    foreach ($robotCards as $rosid => $rocards){
                        $ulevs = FALSE ;
                        if (!empty($tempuserSids) && in_array($rosid, $tempuserSids)) continue; //玩家用户
                        
                        //TODO 比牌操作
                        $res_dui = self::compareGameCardSize($gameId ,$pcards ,$rocards,$ulevs);
                        BaseEnum::Logger("TODO=====>比牌中  玩家(UID={$pUid},UseatId ={$pseatId})-->>>玩家牌值：" . json_encode(["u--".$pseatId=>$pcards,"rob--".$rosid=>$rocards,"last_result"=> $res_dui])."  =====> 比牌结果：".json_encode($ulevs) , 'user-login');
                        //TODO 处理牌的对比操作计算，
                        if($res_dui === TRUE){                      //对于大牌，才处理调换
                            $robotCards[$rosid] = $pcards;          //对调两个位置的值( 换方案处理 )
                            $robotCards[$pseatId] = $rocards;       //玩家的换掉
                            $pcards = $rocards;                     //对换
                        }
                    }
                }
                
                //组合两个数组
                if(!empty($robotCards)){
                    BaseEnum::Logger("第三步：比牌完成 -->>>组装成新的牌局值：" . json_encode($robotCards)."  =====> 游戏人数：".sizeof($robotCards), 'user-login');
                    $cardList = $robotCards ;
                }
            }
        }
        return TRUE;
    }
    
    
    //TODO 玩家跟其它位比手牌大小值
    protected static function compareGameCardSize($gameId ,$pcards ,$rocards,& $levels = false){
        $userLev = $robLev = FALSE;
        if(!$gameId || empty($pcards) || empty($rocards) || sizeof($pcards) != sizeof($rocards)) return FALSE;
        //比牌大小值；
        if($gameId == 101){
            CardEnum::dealNiuNiuLevel($pcards,$userLev);
            CardEnum::dealNiuNiuLevel($rocards,$robLev);
        }
        
        
        $levels = ["u"=>$userLev,"rob_levl"=> $robLev];
        //TODO 等级大小判断是否比牌输掉
        if($userLev!==FALSE && $robLev !==FALSE && $robLev < $userLev){
            return TRUE;
        }
        return FALSE;   
    }
    
    
    /**
     * TODO 通知赢的内容
     * @param number $gameId
     */
    public static function getNoticeCache($gameId,$maxNum = 10) {
        
        $notice_key = SysEnum::USERWIN_NOTICE_KEY . $gameId;
        $result = RedisTools::Pool_hGetAll($notice_key);
        
        $alltimes = FALSE;
        $noticeList = [];
        if(!empty($result)){
            foreach ($result as $r => $reone){
                $reone = !empty($reone) ? json_decode($reone,TRUE): FALSE;
                $onecont = $reone['content'] ?? FALSE;
                if (!empty($reone) && isset($reone['timestamp']) && $onecont) {
                    $noticeList[$r] = $reone;
                }
            }
            if (!empty($noticeList)) {
                $alltimes = array_keys($noticeList);
                $count = sizeof($noticeList);
                @array_multisort($alltimes,SORT_DESC,$noticeList);    //列表排序
                $noticeList = array_values($noticeList);
                if ($count > $maxNum) {
                    $noticeList = array_slice($noticeList, 0,$maxNum);
                }
            }
        }
        BaseEnum::Logger("获取通知：logger-GameId={$notice_key} , 游戏数据： ".json_encode($alltimes) ,"user-login");
        
        return $noticeList ??FALSE;
    }
    
    
    //TODO 消息模板
    protected static function createMsgModel($maxUser,$roomName="") {
        $userName = $maxUser['userName'] ?? "";
        $winPoints = $maxUser['changeMoney'] ?? 0;
        if(!$maxUser || empty($roomName) || !$userName || floatval($winPoints) <= 0)return false;
        $hiddenName = BaseComm::hiddenUserName($userName);
        //消息模板随机取样
        $msgLists = [
            "恭喜玩家<color=red>{$hiddenName}</color>在<color=red>{$roomName}</color>赢得<color=green>{$winPoints}</color>,简直是天上掉馅饼~~~!",
            "恭喜玩家<color=red>{$hiddenName}</color>鸿运当头，在<color=red>{$roomName}</color>赢了<color=green>{$winPoints}</color>,气氛太火爆了~~~!",
            "恭喜玩家<color=red>{$hiddenName}</color>鸿运当头，在<color=red>{$roomName}</color>赢了<color=green>{$winPoints}</color>,真是游戏一分钟，少打十年功!",
            "天啊，玩家<color=red>{$hiddenName}</color>，在<color=red>{$roomName}</color>一把赢得<color=green>{$winPoints}</color>,真是太厉害了!",
            "天啊，玩家<color=red>{$hiddenName}</color>，在<color=red>{$roomName}</color>中沉着冷静，有勇有谋，一举一把赢得<color=green>{$winPoints}</color>厉害!"
        ];
        $randII = array_rand($msgLists,1);
        return $msgLists[$randII] ?? FALSE;
    }
}